$(function () {
  // 初始化界面
  function init() {
    placeholderPic()
    sd1('.sd1')
    sd1('.sd2')
    sd2('.sd3')
    sd2('.sd4')
    jz()
    animate()
  }
  init()

  // 自定义字体大小
  function placeholderPic() {
    w = document.documentElement.clientWidth / 80;
    document.documentElement.style.fontSize = w + 'px';
  }

  // 闪电一,二
  function sd1(ele) {
    var width, height
    var step = 0;
    var canvas = document.createElement('canvas')
    var ctx = canvas.getContext('2d')

    var bg = [4, 10, 11]
    document.querySelector(ele).appendChild(canvas)
    setTimeout(() => {
      var timeID = setInterval(() => {
        pt1.x += 10;
        if (pt1.x > width - 10) {
          clearInterval(timeID)
        }
      }, 60);
    }, 1000)

    var pt1
    var pt2

    window.addEventListener('resize', setup)

    setup()

    function setup() {
      canvas.width = width = document.querySelector(ele).clientWidth
      canvas.height = height = document.querySelector(ele).clientHeight

      ctx.beginPath();
      ctx.rect(0, 0, width, height)
      ctx.fillStyle = `rgba(${bg[0]}, ${bg[1]}, ${bg[2]}, ${1})`
      ctx.fill()

      pt1 = { x: -20, y: height / 2 }//闪电起点
      pt2 = { x: -20, y: height / 2 } //闪电终点
      // draw()
    }

    setInterval(animate, 60)
    // window.requestAnimationFrame(animate);

    function blur(ctx, canvas, amt) {
      ctx.filter = `blur(${amt}px)`
      ctx.drawImage(canvas, 0, 0)
      ctx.filter = 'none'
    }

    function fade(ctx, amt, width, height) {
      ctx.beginPath();
      ctx.rect(0, 0, width, height)
      ctx.fillStyle = `rgba(${bg[0]}, ${bg[1]}, ${bg[2]}, ${amt})`
      ctx.fill()
    }

    function animate() {
      step++

      blur(ctx, canvas, 1)
      draw()
      fade(ctx, 0.1, width, height)

      // window.requestAnimationFrame(function(){animate()})
    }

    function draw() {

      var iterations = [pt1, pt2]
      var newiterations, i, j
      for (i = 0; i < 8; i++) {
        newiterations = [iterations[0]]
        for (j = 1; j < iterations.length; j++) {
          newiterations.push(getRandMidpoint(iterations[j - 1], iterations[j], 200 / (i * i + 1)))
          newiterations.push(iterations[j])
        }
        iterations = newiterations.concat([])
      }
      ctx.beginPath();
      ctx.moveTo(iterations[0].x, iterations[0].y);
      ctx.lineWidth = 2;
      ctx.strokeStyle = '#04e4c9';
      // ctx.strokeStyle = `hsla(${Math.sin( step / 30) * 120 + 50},${90}%,${70}%,1)`
      for (i = 1; i < iterations.length; i++) {
        ctx.lineTo(iterations[i].x, iterations[i].y);
      }
      ctx.stroke()
      ctx.closePath()
    }

    function getRandMidpoint(pa, pb, range) {
      var a = Math.atan2(pb.y - pa.y, pb.x - pa.x) + Math.PI / 2
      var half = { y: (pb.y - pa.y) / 2 + pa.y, x: (pb.x - pa.x) / 2 + pa.x }
      var offset = Math.random() * range / 3 - range / 6  //这里控制闪电的抖动幅度
      var ho = {
        x: Math.cos(a) * offset + half.x,
        y: Math.sin(a) * offset + half.y
      }
      return ho
    }
  }


  //
  //
  //

  // 闪电三,四
  function sd2(ele) {
    var width, height
    var step = 0;
    var canvas = document.createElement('canvas')
    var ctx = canvas.getContext('2d')

    var bg = [4, 10, 11]
    document.querySelector(ele).appendChild(canvas)
    setTimeout(() => {
      var timeID = setInterval(() => {
        pt1.x -= 10;
        if (pt1.x < 10) {
          clearInterval(timeID)
        }
      }, 60);
    }, 1000)

    var pt1
    var pt2

    window.addEventListener('resize', setup)

    setup()

    function setup() {
      canvas.width = width = document.querySelector(ele).clientWidth
      canvas.height = height = document.querySelector(ele).clientHeight

      ctx.beginPath();
      ctx.rect(0, 0, width, height)
      ctx.fillStyle = `rgba(${bg[0]}, ${bg[1]}, ${bg[2]}, ${1})`
      ctx.fill()

      pt1 = { x: width + 20, y: height / 2 }//闪电起点
      pt2 = { x: width + 20, y: height / 2 } //闪电终点
      // draw()
    }

    setInterval(animate, 60)
    // window.requestAnimationFrame(animate);

    function blur(ctx, canvas, amt) {
      ctx.filter = `blur(${amt}px)`
      ctx.drawImage(canvas, 0, 0)
      ctx.filter = 'none'
    }

    function fade(ctx, amt, width, height) {
      ctx.beginPath();
      ctx.rect(0, 0, width, height)
      ctx.fillStyle = `rgba(${bg[0]}, ${bg[1]}, ${bg[2]}, ${amt})`
      ctx.fill()
    }

    function animate() {
      step++

      blur(ctx, canvas, 1)
      draw()
      fade(ctx, 0.1, width, height)

      // window.requestAnimationFrame(function(){animate()})
    }

    function draw() {

      var iterations = [pt1, pt2]
      var newiterations, i, j
      for (i = 0; i < 8; i++) {
        newiterations = [iterations[0]]
        for (j = 1; j < iterations.length; j++) {
          newiterations.push(getRandMidpoint(iterations[j - 1], iterations[j], 200 / (i * i + 1)))
          newiterations.push(iterations[j])
        }
        iterations = newiterations.concat([])
      }
      ctx.beginPath();
      ctx.moveTo(iterations[0].x, iterations[0].y);
      ctx.lineWidth = 2;
      ctx.strokeStyle = '#04e4c9';
      // ctx.strokeStyle = `hsla(${Math.sin( step / 30) * 120 + 50},${90}%,${70}%,1)`
      for (i = 1; i < iterations.length; i++) {
        ctx.lineTo(iterations[i].x, iterations[i].y);
      }
      ctx.stroke()
      ctx.closePath()
    }

    function getRandMidpoint(pa, pb, range) {
      var a = Math.atan2(pb.y - pa.y, pb.x - pa.x) + Math.PI / 2
      var half = { y: (pb.y - pa.y) / 2 + pa.y, x: (pb.x - pa.x) / 2 + pa.x }
      var offset = Math.random() * range / 3 - range / 6  //这里控制闪电的抖动幅度
      var ho = {
        x: Math.cos(a) * offset + half.x,
        y: Math.sin(a) * offset + half.y
      }
      return ho
    }
  }

  // 加载动画
  function jz() {
    $('.jz1 ul li').each((index, item) => {
      item.style.opacity = 1 - index / 10;
    })
    setInterval(() => {
      $('.jz1 ul li').each((index, item) => {
        if (item.style.opacity == 0) {
          item.style.opacity = 1
        }
        item.style.opacity = parseFloat(item.style.opacity) - 0.1
      })
    }, 100)
    $('.jz2 ul li').each((index, item) => {
      item.style.opacity = 1 - index / 10;
    })
    setInterval(() => {
      $('.jz2 ul li').each((index, item) => {
        if (item.style.opacity == 0) {
          item.style.opacity = 1
        }
        item.style.opacity = parseFloat(item.style.opacity) - 0.1
      })
    }, 100)
  }

  // 中间背景动画
  function animate() {
    var App = {};
    App.setup = function () {
      // 创建canvas元素，并加入body中
      var canvas = document.createElement('canvas');
      this.filename = "spipa";
      // 控制canvas幕布的大小
      canvas.width = document.querySelector('.animate').clientWidth;
      canvas.height = document.querySelector('.animate').clientHeight;
      this.canvas = canvas;
      document.querySelector('.animate').appendChild(canvas);
      this.ctx = this.canvas.getContext('2d');
      this.width = this.canvas.width;
      this.height = this.canvas.height;
      this.dataToImageRatio = 1;
      this.ctx.imageSmoothingEnabled = false;
      this.ctx.webkitImageSmoothingEnabled = false;
      this.ctx.msImageSmoothingEnabled = false;
      this.xC = this.width / 2;
      this.yC = this.height / 2;

      this.stepCount = 0;
      this.particles = [];
      this.lifespan = 1000;
      this.popPerBirth = 1;
      this.maxPop = 200;
      this.birthFreq = 5;

      // Build grid
      this.gridSize = 8;// 运动坐标
      this.gridSteps = Math.floor(1000 / this.gridSize);
      this.grid = [];
      var i = 0;
      for (var xx = -500; xx < 500; xx += this.gridSize) {
        for (var yy = -500; yy < 500; yy += this.gridSize) {
          // 径向场，r的三角函数，最大值在r0附近
          var r = Math.abs(xx) + Math.abs(yy),//Math.sqrt(xx*xx+yy*yy),
            r0 = 3 * w, //中间方形的大小
            field;

          if (r < r0) field = 255 / r0 * r;
          else if (r > r0) field = 255 - Math.min(255, (r - r0) / 2);

          this.grid.push({
            x: xx,
            y: yy,
            busyAge: 0,
            spotIndex: i,
            isEdge: (xx == -500 ? 'left' :
              (xx == (-500 + this.gridSize * (this.gridSteps - 1)) ? 'right' :
                (yy == -500 ? 'top' :
                  (yy == (-500 + this.gridSize * (this.gridSteps - 1)) ? 'bottom' :
                    false
                  )
                )
              )
            ),
            field: field
          });
          i++;
        }
      }
      this.gridMaxIndex = i;



      this.initDraw();
    };
    App.evolve = function () {
      var time1 = performance.now();

      this.stepCount++;

      // Increment all grid ages
      this.grid.forEach(function (e) {
        if (e.busyAge > 0) e.busyAge++;
      });

      if (this.stepCount % this.birthFreq == 0 && (this.particles.length + this.popPerBirth) < this.maxPop) {
        this.birth();
      }
      App.move();
      App.draw();

      var time2 = performance.now();



    };
    App.birth = function () {
      var x, y;
      var gridSpotIndex = Math.floor(Math.random() * this.gridMaxIndex),
        gridSpot = this.grid[gridSpotIndex],
        x = gridSpot.x, y = gridSpot.y;

      var particle = {
        hue: -10,// + Math.floor(50*Math.random()),
        sat: 95,//30 + Math.floor(70*Math.random()),
        lum: 20 + Math.floor(40 * Math.random()),
        x: x, y: y,
        xLast: x, yLast: y,
        xSpeed: 0, ySpeed: 0,
        age: 0,
        ageSinceStuck: 0,
        attractor: {
          oldIndex: gridSpotIndex,
          gridSpotIndex: gridSpotIndex,// Pop at random position on grid
        },
        name: 'seed-' + Math.ceil(10000000 * Math.random())
      };
      this.particles.push(particle);
    };
    App.kill = function (particleName) {
      var newArray = _.reject(this.particles, function (seed) {
        return (seed.name == particleName);
      });
      this.particles = _.cloneDeep(newArray);
    };
    App.move = function () {
      for (var i = 0; i < this.particles.length; i++) {
        // Get particle
        var p = this.particles[i];

        // Save last position
        p.xLast = p.x; p.yLast = p.y;

        // Attractor and corresponding grid spot
        var index = p.attractor.gridSpotIndex,
          gridSpot = this.grid[index];

        // Maybe move attractor and with certain constraints
        if (Math.random() < 0.5) {
          // Move attractor
          if (!gridSpot.isEdge) {
            // Change particle's attractor grid spot and local move function's grid spot
            var topIndex = index - 1,
              bottomIndex = index + 1,
              leftIndex = index - this.gridSteps,
              rightIndex = index + this.gridSteps,
              topSpot = this.grid[topIndex],
              bottomSpot = this.grid[bottomIndex],
              leftSpot = this.grid[leftIndex],
              rightSpot = this.grid[rightIndex];

            // Choose neighbour with highest field value (with some desobedience...)
            var chaos = 30;
            var maxFieldSpot = _.maxBy([topSpot, bottomSpot, leftSpot, rightSpot], function (e) {
              return e.field + chaos * Math.random()
            });

            var potentialNewGridSpot = maxFieldSpot;
            if (potentialNewGridSpot.busyAge == 0 || potentialNewGridSpot.busyAge > 15) {// Allow wall fading
              //if (potentialNewGridSpot.busyAge == 0) {// Spots busy forever
              // Ok it's free let's go there
              p.ageSinceStuck = 0;// Not stuck anymore yay
              p.attractor.oldIndex = index;
              p.attractor.gridSpotIndex = potentialNewGridSpot.spotIndex;
              gridSpot = potentialNewGridSpot;
              gridSpot.busyAge = 1;
            } else p.ageSinceStuck++;

          } else p.ageSinceStuck++;

          if (p.ageSinceStuck == 10) this.kill(p.name);
        }

        // Spring attractor to center with viscosity
        var k = 8, visc = 0.4;
        var dx = p.x - gridSpot.x,
          dy = p.y - gridSpot.y,
          dist = Math.sqrt(dx * dx + dy * dy);

        // Spring
        var xAcc = -k * dx,
          yAcc = -k * dy;

        p.xSpeed += xAcc; p.ySpeed += yAcc;

        // Calm the f*ck down
        p.xSpeed *= visc; p.ySpeed *= visc;

        // Store stuff in particle brain
        p.speed = Math.sqrt(p.xSpeed * p.xSpeed + p.ySpeed * p.ySpeed);
        p.dist = dist;

        // Update position
        p.x += 0.1 * p.xSpeed; p.y += 0.1 * p.ySpeed;

        // Get older
        p.age++;

        // Kill if too old
        if (p.age > this.lifespan) {
          this.kill(p.name);
          this.deathCount++;
        }
      }
    };
    App.initDraw = function () {
      this.ctx.beginPath();
      this.ctx.rect(0, 0, this.width, this.height);
      this.ctx.fillStyle = 'transparent';
      this.ctx.fill();
      this.ctx.closePath();
    };

    App.draw = function () {
      this.drawnInLastFrame = 0;
      if (!this.particles.length) return false;

      this.ctx.beginPath();
      this.ctx.rect(0, 0, this.width, this.height);
      // this.ctx.fillStyle = 'transparent';
      this.ctx.fillStyle = 'rgba(12, 22, 25, 0.1)';
      this.ctx.fill();
      this.ctx.closePath();
      for (var i = 0; i < this.particles.length; i++) {
        // Draw particle
        var p = this.particles[i];

        var h, s, l, a;

        h = p.hue + this.stepCount / 30;
        s = p.sat;
        l = p.lum;
        a = 1;

        var last = this.dataXYtoCanvasXY(p.xLast, p.yLast),
          now = this.dataXYtoCanvasXY(p.x, p.y);
        var attracSpot = this.grid[p.attractor.gridSpotIndex],
          attracXY = this.dataXYtoCanvasXY(attracSpot.x, attracSpot.y);
        var oldAttracSpot = this.grid[p.attractor.oldIndex],
          oldAttracXY = this.dataXYtoCanvasXY(oldAttracSpot.x, oldAttracSpot.y);

        this.ctx.beginPath();

        this.ctx.strokeStyle = 'green';
        this.ctx.fillStyle = 'hsla(' + h + ', ' + s + '%, ' + l + '%, ' + a + ')';

        // Particle trail
        this.ctx.moveTo(last.x, last.y);
        this.ctx.lineTo(now.x, now.y);

        this.ctx.lineWidth = 1.5 * this.dataToImageRatio;
        this.ctx.stroke();
        this.ctx.closePath();

        // Attractor positions
        this.ctx.beginPath();
        this.ctx.lineWidth = 1.5 * this.dataToImageRatio;
        this.ctx.moveTo(oldAttracXY.x, oldAttracXY.y);
        this.ctx.lineTo(attracXY.x, attracXY.y);
        this.ctx.arc(attracXY.x, attracXY.y, 1.5 * this.dataToImageRatio, 0, 2 * Math.PI, false);

        //a /= 20;
        this.ctx.strokeStyle = 'green';
        this.ctx.fillStyle = 'green';
        //this.ctx.stroke();
        this.ctx.fill();

        this.ctx.closePath();

        // UI counter
        this.drawnInLastFrame++;
      }

    };
    App.dataXYtoCanvasXY = function (x, y) {
      var zoom = 1.6;
      var xx = this.xC + x * zoom * this.dataToImageRatio,
        yy = this.yC + y * zoom * this.dataToImageRatio;

      return { x: xx, y: yy };
    };

    setTimeout(function () {
      App.setup();
      App.draw();

      var frame = function () {
        App.evolve();
        requestAnimationFrame(frame);
      };
      frame();
    }, 5000)


    /**
     * Some old util I use at times
     *
     * @param {Number} Xstart X value of the segment starting point
     * @param {Number} Ystart Y value of the segment starting point
     * @param {Number} Xtarget X value of the segment target point
     * @param {Number} Ytarget Y value of the segment target point
     * @param {Boolean} realOrWeb true if Real (Y towards top), false if Web (Y towards bottom)
     * @returns {Number} Angle between 0 and 2PI
     */
    segmentAngleRad = function (Xstart, Ystart, Xtarget, Ytarget, realOrWeb) {
      var result;// Will range between 0 and 2PI
      if (Xstart == Xtarget) {
        if (Ystart == Ytarget) {
          result = 0;
        } else if (Ystart < Ytarget) {
          result = Math.PI / 2;
        } else if (Ystart > Ytarget) {
          result = 3 * Math.PI / 2;
        } else { }
      } else if (Xstart < Xtarget) {
        result = Math.atan((Ytarget - Ystart) / (Xtarget - Xstart));
      } else if (Xstart > Xtarget) {
        result = Math.PI + Math.atan((Ytarget - Ystart) / (Xtarget - Xstart));
      }

      result = (result + 2 * Math.PI) % (2 * Math.PI);

      if (!realOrWeb) {
        result = 2 * Math.PI - result;
      }

      return result;
    }
  }
})